fix: show app and environment when a path filter matches no secrets - #318
Merged
Conversation
`phase run` and `phase shell` derived the Application and Environment
labels from the fetched secret rows. When the fetch returned nothing they
printed blank names:
🚀 Injected 0 secrets from Application: , Environment:
This is easy to hit: both commands default to `--path /`, paths are
matched exactly, so an app whose secrets all live in folders injects zero
secrets at the default path. The blank names then read as a failure to
resolve the app — e.g. an unreadable .phase.json — rather than a path
filter that matched nothing.
Resolve the names from the account's app list when no result row carries
them, so the queried app and environment are always reported. The lookup
only runs on the empty path, leaving the normal path free of extra
requests. `phase secrets list` had the same root cause: its header read
`secrets[0]`, so an empty result printed a bare "No secrets to display."
with no context at all. It now renders the resolved context too.
Also say why the result was empty, since exact-path matching is the usual
reason: `run`, `shell`, `secrets list` and `secrets export` point at
`--path ""` to search all paths, and `secrets get` says which path it
searched. The `export` note goes to stderr so piped output stays clean.
`phase shell` additionally left PHASE_APP and PHASE_ENV unset whenever
zero secrets were loaded; they now follow the resolved context.
rohan-chaturvedi
self-requested a review
August 6, 2026 09:48
Deploying phase-cli-install-script with
|
| Latest commit: |
ff4526a
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://46cf86f5.phase-cli-install-script.pages.dev |
| Branch Preview URL: | https://claude-empty-app-env-fields.phase-cli-install-script.pages.dev |
- ResolveNames reads the SDK's userdata.json cache before the network, never hits the network in offline mode, and falls back to the app ID so labels are never blank - empty-result hints name a --tags filter when one was applied - keyed secrets export miss names the searched path - httptest coverage for the name resolution success paths
rohan-chaturvedi
force-pushed
the
claude/empty-app-env-fields-69b222
branch
from
August 7, 2026 08:46
3e39298 to
ff4526a
Compare
rohan-chaturvedi
approved these changes
Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
phase runandphase shellprinted blank Application and Environment labels whenever the fetch returned no secrets:This is easy to hit. Both commands default to
--path /, and paths are matched exactly — so an app whose secrets all live in folders injects zero secrets at the default path. The blank names then read as a failure to resolve the app (an unreadable.phase.json, bad credentials) rather than what actually happened: a path filter that matched nothing.Root cause
run.goandshell.goderived the labels from the fetched secret rows:No rows → no names →
strings.Join(nil, ", ")→"".phase secrets listhad the same root cause inRenderSecretsTree, which readsecrets[0].Application; an empty result fell through to a bareNo secrets to display.with no context at all. (Both behaviours were faithfully ported from the Python CLI, which has the same defect.)The fix
Always report the queried app and environment. When no result row carries the names, resolve them from the account's app list via a new
phase.ResolveNames. The lookup only runs on the empty path, so the normal path takes no extra requests. Selectors are normalised to canonical names on the way through —--app 3 --env dev,--app-id <uuid>, and.phase.jsonall reportApplication: 3, Environment: Development.Explain why the result was empty, since exact-path matching is the usual reason.
run,shell,secrets listandsecrets exportnow point at--path "", andsecrets getnames the path it searched. The hint is suppressed when no path filter was applied — there, every path was already searched and the suggestion would be a dead end. Theexportnote goes to stderr so piped output stays byte-identical.phase shellalso leftPHASE_APPandPHASE_ENVunset whenever zero secrets were loaded; they now follow the resolved context.No change to
--pathdefaults or filtering semantics — those are documented behaviour (Default is '/'. Pass an empty string "" to fetch secrets from all paths) and match the Python CLI.Before / after
Test app with secrets only under
/oneand/two, nothing at the root:phase run🚀 Injected 0 secrets from Application: , Environment:🚀 Injected 0 secrets from Application: 3, Environment: Development💡 No secrets found at path /. Secrets under other paths are not included — pass --path "" to inject secrets from all paths.phase secrets list --path /No secrets to display.🔮 No secrets found for Application: 3, Environment: Development💡 Nothing at path /. Secrets under other paths are not listed — pass --path "" to list secrets from all paths.phase secrets get SECRET_1Error: 🔍 No matching secrets foundError: 🔍 No matching secrets found at path / — secrets under other paths are not searched. Pass --path "" to search all pathsphase secrets export💡 No secrets found at path /. …phase shellPHASE_APP/PHASE_ENVunsetVerification
Reproduced and verified end to end against a local Console, using a user token and an app with secrets only in folders:
--app/--env, partial/lowercase--env dev,--app-idalone, and.phase.json--path /one,--path "", and unfilteredsecrets listrender as beforesecrets create/delete(which route throughlistSecrets) render correctly--path ""gets no misleading hintphase shellsetsPHASE_APP=3 PHASE_ENV=Developmentwith zero secrets loadedsecrets export | …stdout unchanged — the note is stderr-onlygo build,go vet,gofmt,go test ./...all cleanNew unit tests cover the empty-result renderer, the context-name fallback, and hint suppression when no path filter is set.
🤖 Generated with Claude Code